# -*- coding: utf-8 -*-
# @Time    : 2024/7/30 16:04
# @Author  : yujiahao
# @File    : 68_fastapi_websocket.py
# @description:WebSockets


"""
WebSockets 客户端

在生产环境中：
1. 使用现代前端框架：
   - 我们可能使用 React、Vue.js 或 Angular 等现代框架创建前端。
   - 这些框架提供了与 WebSockets 通信的工具和库。

2. 原生移动应用：
   - 我们可能有一个原生移动应用程序，直接使用原生代码与 WebSocket 后端通信。

3. 其他通信方式：
   - 我们可能有其他方式与 WebSocket 终端进行通信。

示例说明：
- 在本示例中，我们使用一个简单的 HTML 文档，其中包含一些 JavaScript，全部放在一个长字符串中。
- 这种方法仅用于演示 WebSockets 的服务器端实现，并提供一个工作示例。
- 注意：这种方法并不是生产环境中的最佳实践。

生产环境建议：
- 在生产环境中，我们应选择上述任一选项，而不是使用简单的 HTML 和 JavaScript 字符串。
"""

# 导入 websocket 依赖
from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()
html = """
<!DOCTYPE html>
<html>
    <head>
        <!-- 设置网页的标题，将在浏览器标签页中显示 -->
        <title>Chat</title>
    </head>
    <body>
        <!-- 页面主体 -->
        <!-- h1元素表示一级标题 -->
        <h1>WebSocket Chat</h1>

        <!-- 表单，用于发送消息 -->
        <!-- onsubmit属性指定表单提交时调用sendMessage函数 -->
        <form action="" onsubmit="sendMessage(event)">
            <!-- 输入框，用户可以在此输入消息 -->
            <!-- id属性用于在JavaScript中引用这个元素 -->
            <input type="text" id="messageText" autocomplete="off"/>
            <!-- 提交按钮 -->
            <button>Send</button>
        </form>

        <!-- 无序列表，用于显示消息 -->
        <!-- id属性用于在JavaScript中引用这个元素 -->
        <ul id='messages'>
        </ul>

        <!-- 内联JavaScript脚本 -->
        <script>
            // 创建一个新的WebSocket连接，连接到服务器的/ws端点
            var ws = new WebSocket("ws://localhost:8000/ws");

            // 定义当收到服务器消息时的处理函数
            ws.onmessage = function(event) {
                // 获取消息列表的DOM元素
                var messages = document.getElementById('messages');
                // 创建一个新的列表项元素
                var message = document.createElement('li');
                // 创建一个文本节点，内容是收到的消息
                var content = document.createTextNode(event.data);
                // 将文本节点添加到列表项元素中
                message.appendChild(content);
                // 将列表项元素添加到消息列表中
                messages.appendChild(message);
            };

            // 定义发送消息的函数
            function sendMessage(event) {
                // 获取输入框的DOM元素
                var input = document.getElementById("messageText");
                // 通过WebSocket发送输入框中的消息
                ws.send(input.value);
                // 清空输入框
                input.value = '';
                // 阻止表单的默认提交行为
                event.preventDefault();
            }
        </script>
    </body>
</html>
"""


@app.get("/")
async def get():
    return HTMLResponse(html)


# 创建 websocket
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    # 所有这些消息都将使用同一个 WebSocket 连接。
    # 可以使用 await 等待消息并发送消息。
    await websocket.accept()
    while True:
        # 可以接收和发送二进制、文本和 JSON 数据。
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")


